/****************************************************************
Christian Klugesherz
Novembre 2014
Programme de gestion thermostatique

Based  : 
     http://arduino.cc/en/Tutorial/WebServer
     https://learn.adafruit.com/adafruit-cc3000-wifi-and-xively/arduino-sketch
     http://i-arduino.blogspot.fr/p/iarduino-tutorial.html
-----------------------------------------------------------------

Arduino PIN

+5V       VCC or +5V      5V
GND        GND             GND

CC3000      
Uno Pin    CC3000 Board    Function
3          INT             Interrupt			(CC3000)
4          SD_CS           SD Chip Select		(SD)
5          EN              VBAT EN Module 		(CC3000)
10         CS              SPI Chip Select 		(CC3000)
11         MOSI            SPI MOSI			(SD/CC3000)
12         MISO            SPI MISO			(SD/CC3000)
13         SCK             SPI Clock 			(SD/CC3000)
RS232
0      RX
1      TX
Thermostat
8

Free
2
6
7
9
****************************************************************/
#include <Adafruit_CC3000.h>
#include <SPI.h>
#include <avr/wdt.h>
//#include "utility/debug.h"
//#include "utility/socket.h" 

//------------------------------------------------------------------------------------------
// ----------------------------------------DEFINE------------------------------------------- 
//------------------------------------------------------------------------------------------
#define DEBUG 1

#define ADAFRUIT_CC3000_IRQ   3 
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

#define WLAN_SSID       "NETGEAR-1"  
//#define WLAN_SSID       "Freebox-Cave"  
#define WLAN_PASS       "377A2D0C33"

#define WLAN_SECURITY   WLAN_SEC_WPA2	// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define LISTEN_PORT     23      		// What TCP port to listen on for connections. 

#define THERMOSTAT_PIN     8      		// Output port to control thermostat
#define TEMP_PIN     	   0      		// LM35 temperature analog pin

//------------------------------------------------------------------------------------------
// ----------------------------------------VARIABLES---------------------------------------- 
//------------------------------------------------------------------------------------------

/* Initialize Wifi Shield CC3000 */
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,SPI_CLOCK_DIVIDER); 

/* Initialize the Ethernet server with the IP address and port to use */
Adafruit_CC3000_Server tcp_server(LISTEN_PORT);


/* Static IP address */
uint32_t ipAddress = cc3000.IP2U32(192, 168, 1, 30);
uint32_t netMask = cc3000.IP2U32(255, 255, 255, 0);
uint32_t defaultGateway = cc3000.IP2U32(192, 168, 1, 254);
uint32_t dns = cc3000.IP2U32(192,168,1,254);

//---------------------------------------------------------------------------------------------------
//--------------------------------------------- FUNCTION --------------------------------------------
//---------------------------------------------------------------------------------------------------

/************************************************************************ 
  Convert integer + 1 decimal to string
  
  itoa_p(buffer,4,105) = "10.5"

 Example
    nb = 255  --> nb_len = 4

      indice     0 1 2 3  4
    buffer  =    2 5 . 5 \0

    nb = -255  --> nb_len = 5

      indice     0 1 2 3 4 5
    buffer  =    - 2 5 . 5 \0
 ************************************************************************/
char *itoa_p(char *buffer, short nb_len , short nb) {
  unsigned short n;
  unsigned short negate = 0;
  boolean point;
  
  for (n=0;n<nb_len;n++) {
    buffer[n] = '0';
  }
  
  if (nb < 0) {
    negate=1;
    n = -nb;
  } else {
    n = nb;
  }
  buffer[nb_len--] = '\0';
  
  point = true;    
  do {
    buffer[nb_len--] = (n % 10) + '0';
    if (point) {
      point = false;
      buffer[nb_len--] = '.';
    }
    n = n / 10;
  } while (n);
  
  if (negate) {
    buffer[nb_len--] = '-';
  }
  return &buffer[0];
}

/************************************************************************ 
 Tries to read the IP address and other connection details
************************************************************************/
#ifdef DEBUG
bool displayConnectionDetails(void) {
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
  
  if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))  {
    Serial.println(F("Unable to retrieve the IP Address!\r\n"));
    return false;
  }  else  {
    Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
    Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
    Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
    Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
    Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
    Serial.println();
    return true;
  }
}
#endif

/************************************************************************ 
 Read Temperature
 https://www.timdejong.nl/blog/get-accurate-temperature-lm35-arduino-correctly
 output 121 = 12,1
 ************************************************************************/
int ReadTemp(void) {
  int i;
  int reading; 
  float tempC;
  float referenceVoltage;
  
  referenceVoltage = 1.1; 	//Set to depending on analogReference Setting
  
  reading = 0;
  // Average 10 readings for accurate reading
  for(int i = 0; i < 10; i++) { 
    reading += analogRead(TEMP_PIN);
    delay(20);
  }
  
  // A lot of examples divide the sensor reading by 1024. 
  // This is incorrect and should be 1023. 
  // There are 1024 values including 0 so this should be 1023.
  tempC =  (referenceVoltage * reading * 10) / 1023; 
  // Correction
  tempC = tempC - 6.0;

  //Print one decimal, it's not accurate enough for two
  //Serial.print(tempC, 1); Serial.println(" C");
  
  return( (int)(tempC*10)); 
}

/************************************************************************ 
 ************************************************************************
 SETUP
    As we will connect and disconnect from the server every time we want to send data, 
    the setup() we will only include the initialization of the CC3000 chip, 
    and the connection to the WiFi network: 
 ************************************************************************
 ************************************************************************/
void setup(void)
{
  int i;
  
  /* UART */
  Serial.begin(115200);

  /* Control Thermostat */
  pinMode(THERMOSTAT_PIN,OUTPUT);
  analogReference(INTERNAL);	

  /* Initialise the shield module */
  Serial.println(F("\nInitializing..."));
  if (!cc3000.begin()) {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }

  /* Set Static Address */
  Serial.println(F("\nSet IP Static Address"));
  if (!cc3000.setStaticIPAddress(ipAddress, netMask, defaultGateway, dns)) {
    Serial.println(F("Failed to set static IP!"));
    while(1);
  }

  /* Connect to Wifi Network */
  Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    while(1);
  }
  Serial.println(F("Wifi Connected!"));

#ifdef DEBUG
  // Display the IP address DNS, Gateway, etc.
  while (! displayConnectionDetails()) {
    delay(1000);
  }
#endif

  /* Start the server and start listening for connections */
  /* Server is running all the time */
  tcp_server.begin();
  Serial.println(F("Listening for connections..."));

  /* Indicate by LED blincking that all is working well */
  for (i=0;i<10;i++) {
    digitalWrite(THERMOSTAT_PIN, HIGH);  
    delay(50); 
    digitalWrite(THERMOSTAT_PIN, LOW);
    delay(50);
  }
  
}

// ----------------------------------------------------------
// ----------------------------------------------------------
// The loop function runs over and over again forever
// ----------------------------------------------------------
// ----------------------------------------------------------
void loop(void){
  char packBuff[30] = "";
  int i = 0;
  char c;
  int temp;
  char tempc[7];

  /* We also need to keep in mind that we want the project to run continuously day after day, whatever happens. 
     So if the Arduino cannot connect or crashes when sending the data, we don't want it to freeze and do nothing anymore.
     This is why we need to use the Arduino watchdog. 
     This will basically reset the Arduino if no reset signal is received after a given delay. 
     Here, we will initialise the watchdog with the maximum delay of 8 seconds:   */
  // wdt_enable(WDTO_8S);


  // Return a reference to a client instance which connect to the server
  // De-connection must be done by the client or after a time out
  Adafruit_CC3000_ClientRef client = tcp_server.available();
  if (client) {
    i = 0;

    Serial.println("new client");
    //tcp_server.write("\n>>"); // no sense

    /* -----------------------------------------------------------------------------------------------
      Read information from the client as long as client connected
      client.available() = client sent data to server
     -----------------------------------------------------------------------------------------------*/
    while ( client.connected() ) {

      if ( client.available() ) {
	c = client.read();
	packBuff[i] = c;
	i++;
	if (c == '\n') {
	  Serial.print(packBuff);
	  i=0;
	  
	  // If we get the message "CTH"
	  if (packBuff[0] = 'C' && packBuff[1]=='T' && packBuff[2]=='H') {
	    digitalWrite(THERMOSTAT_PIN,HIGH);    
	    Serial.println("Pin Thermostat ON");   
	    //tcp_server.write("Thermostat is ON\n>>");
	    //Serial.println(F("\n\nClient Deconnected"));
	    //client.close();                        
	  } 
	  // If we get the message "RDT"
	  else if (packBuff[0] = 'R' && packBuff[1]=='D' && packBuff[2]=='T') {
	    /* Read of temperature */
	    temp = ReadTemp();
	    itoa_p(tempc,4,temp);
	    Serial.println(tempc);	
	    tcp_server.write(tempc);  
	    // tcp_server.write("\n");  
	    //Serial.println(F("\n\nClient Deconnected"));
	    //client.close();
	  } 
	  // If we get the message "CTL"
	  else if (packBuff[0] = 'C' && packBuff[1]=='T' && packBuff[2]=='L') {
	    digitalWrite(THERMOSTAT_PIN,LOW);    
	    Serial.println("Pin Thermostat OFF");  
	    //tcp_server.write("Thermostat is OFF\n>>");  
	    //Serial.println(F("\n\nClient Deconnected"));
	    //client.close();
	  } 
	  else if (packBuff[0] = 'E' && packBuff[1]=='X' && packBuff[2]=='I' && packBuff[3]=='T') {
	    Serial.println(F("Got the information to close the connection"));
	    //tcp_server.write("Connection Closed\n>>");  
	    //Serial.println(F("\n\nClient Deconnected"));
	    client.close();
	  }
	  else {
	    Serial.println("Wrong command");       
	    tcp_server.write("Wrong Command\n");   
	    tcp_server.write("  CTH --> High \n"); 
	    tcp_server.write("  CTL --> Low \n"); 
	    tcp_server.write("  RDT --> Read Temp \n"); 
	    tcp_server.write("  EXIT --> Close Connection \n>>"); 
	    //Serial.println(F("\n\nClient Deconnected"));
	    //client.close();
	  }
	  delay(2);
	}      
      } // if ( client.available() ) -->  client sent data
    } // while ( client.connected() ) --> Client is no more connected

    Serial.println(F("Client has been deconnected "));
    Serial.println(F("Nevertheless close client "));
    client.close();
  } // if (client) 

  /* Indicate by LED blincking that all is working well */
  /*for (i=0;i<2;i++) {
    digitalWrite(THERMOSTAT_PIN, HIGH);  
    delay(50); 
    digitalWrite(THERMOSTAT_PIN, LOW);
    delay(50);
    }*/

  //  disable the watchdog until the next loop(): */
  // Reset watchdog & disable
  //wdt_reset();
  //wdt_disable();
  
}
